package com.yp.infrastructure.mdb.mapper;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yp.infrastructure.mdb.exception.EnumErrorMessage;
import com.yp.infrastructure.mdb.exception.PersistentException;
import com.yp.infrastructure.mdb.model.BaseEntity;
import com.yp.infrastructure.mdb.model.Pagination;

import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;

public interface CommonMapper<T extends BaseEntity> extends BaseMapper<T> {

    default int updateFieldValue(String field, String id, Object value) {
        UpdateWrapper<T> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", id).set(field, value);
        return this.update(null, wrapper);
    }

    default Consumer<QueryWrapper<T>> getKeywordFilter(List<String> fieldNames, String keyword, Boolean leftMatch) {
        if (leftMatch)
            return wrapper -> fieldNames.forEach(fieldName -> wrapper.or(x -> x.likeRight(fieldName, keyword)));
        return wrapper -> fieldNames.forEach(fieldName -> wrapper.or(x -> x.eq(fieldName, keyword)));
    }

    /**
     * 返回可用实体，空值不抛出异常
     *
     * @param id id
     * @return t
     */
    default T getInstance(String id) {
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        wrapper.eq("id", id).ne("deleted", 1);
        return selectOne(wrapper);
    }


    default T getOne(QueryWrapper<T> wrapper) {
        wrapper.eq("deleted", 0);
        return selectOne(wrapper);
    }

    default T getOne(QueryWrapper<T> wrapper, Exception e) throws Exception {
        wrapper.eq("deleted", 0);
        T t = selectOne(wrapper);
        if (null == t && e != null) throw e;
        return t;
    }


    /**
     * 返回可用实体,空值抛异常
     *
     * @param id 实体id
     * @param e  用户输入的异常
     * @return t
     */
    default T getInstance(String id, Exception e) throws Exception {
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        wrapper.eq("id", id).ne("deleted", 1);
        T t = selectOne(wrapper);
        if (t == null && e != null) throw e;
        return t;
    }

    /**
     * delete = true，反回已删实体
     * delete = false 返回可用实体
     * delete = null, 不区分是否被删除
     *
     * @param id      id
     * @param deleted deleted
     * @return t
     */
    default T getInstance(String id, Boolean deleted) {
        if (null == deleted) return selectById(id);
        if (deleted) {
            QueryWrapper<T> wrapper = new QueryWrapper<>();
            wrapper.eq("id", id).eq("deleted", 1);
            return selectOne(wrapper);
        }
        return this.getInstance(id);
    }

    /**
     * 逻辑删除
     *
     * @param id .
     */
    default void deleteInstance(String id) {
        updateFieldValue("deleted", id, 1);
    }

    /**
     * 逻辑删除
     *
     * @param t {@link BaseEntity}
     */
    default void deleteInstance(T t) {
        t.setDeleted(true);
        save(t);
    }


    /**
     * 物理删除
     *
     * @param id .
     */
    default void removeInstance(String id) {
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        wrapper.eq("id", id);
        this.delete(wrapper);
    }

    /**
     * 保存: 插入或更新.
     *
     * @param instance instance.
     */
    default void save(T instance) throws PersistentException {

        try {
            if (StringUtils.isBlank(instance.getId())) {
                instance.setId(UUID.randomUUID().toString());
                instance.setCreationDate(new Date());
                instance.setDeleted(false);
                insert(instance);
                return;
            }
            T tmp = selectById(instance.getId());
            if (null == tmp) {
                instance.setCreationDate(new Date());
                instance.setDeleted(false);
                insert(instance);
                return;
            }
            instance.setUpdatedDate(new Date());
            this.updateById(instance);
        } catch (Exception e) {
            throw new PersistentException(EnumErrorMessage.SQL_ERROR, e);
        }

    }


    /**
     * 返回可用实体列表, 默认加上deleted != 1的条件
     *
     * @param wrapper query
     * @return list.
     */
    default List<T> getList(QueryWrapper<T> wrapper) {
        wrapper.ne("deleted", 1);
        return selectList(wrapper);
    }

    default List<T> getAll() {
        return selectList(null);
    }


    /**
     * 通用分页
     *
     * @param wrapper  wrapper
     * @param currPage currPage
     * @param pageSize pageSize
     * @return pagination
     */
    default Pagination pagination(QueryWrapper<T> wrapper, int currPage, int pageSize) {
        IPage<T> page = page(wrapper, currPage, pageSize);
        Pagination pagination = new Pagination();
        pagination.setData(page.getRecords());
        pagination.setPages(Long.valueOf(page.getPages()).intValue());
        pagination.setCurr(Long.valueOf(page.getCurrent()).intValue());
        pagination.setTotal(Long.valueOf(page.getTotal()).intValue());
        return pagination;
    }

    /**
     * 通用分页
     *
     * @param wrapper  wrapper
     * @param currPage currPage
     * @param pageSize pageSize
     * @return pagination
     */
    default IPage<T> page(QueryWrapper<T> wrapper, int currPage, int pageSize) {
        IPage<T> parameters = new Page<>((long) (currPage - 1) * pageSize, pageSize);
        return selectPage(parameters, wrapper);
    }


}
